using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.MediaCenter;
using Microsoft.MediaCenter.UI;
using Microsoft.MediaCenter.TV.Scheduling;
using Argotic.Syndication;
using MCEMediaManager.Data;
using MCEMediaManager.Model;
using System.Diagnostics;

namespace MCEMediaManager
{
    class TVRssPlugin : MediaPlugin, IMediaPlugin
    {
        private VirtualList _SearchResults;

        public VirtualList SearchResults
        {
            get 
            {
                if (_SearchResults == null)
                {
                    _SearchResults = new VirtualList();
                }
                return (this._SearchResults); 
            }
            set { this._SearchResults = value; }
        }

        private Dictionary<string, VirtualList> _SearchResultsList;

        public Dictionary<string, VirtualList> SearchResultsList
        {
            get
            {
                if (_SearchResultsList == null)
                {
                    _SearchResultsList = new Dictionary<string, VirtualList>();
                }
                return _SearchResultsList;
            }
            set { this._SearchResultsList = value; }
        }

        public override string Name
        {
            get{ return "tvRSS";}
        }

        public string SearchURL
        {
            get
            {
                string value = (string)Application.Current.DataStore.GetString("TVRssSearchURL", "http://ezrss.it/search/index.php?simple&mode=rss&show_name=");
                return value;
            }
            set
            {
                Application.Current.DataStore.SetValue("TVRssSearchURL", value);
            }
        }

        public string SearchURLOptions
        {
            get
            {
                string value = (string)Application.Current.DataStore.GetString("TVRssSearchURLOptions", "");
                return value;
            }
            set
            {
                Application.Current.DataStore.SetValue("TVRssSearchURLOptions", value);
            }
        }

        public override void SearchByName(object obj)
        {
            SearchArgs args = (SearchArgs)obj;
            RssFeed feed = new RssFeed();
            try
            {
                feed = RssFeed.Create(new Uri(SearchURL + args.SearchPage.SearchText + SearchURLOptions));
            }
            catch
            {
                if (!SearchResultsList.ContainsKey("All"))
                {
                    Microsoft.MediaCenter.UI.Application.DeferredInvoke(new DeferredHandler(CreateNewSearchList), "All");
                }
                return;
            }
            this.Filters = new List<string>();
            Microsoft.MediaCenter.UI.Application.DeferredInvoke(delegate { SearchResults.Clear(); });
            foreach (RssItem item in feed.Channel.Items)
            {
                Debug.WriteLine(item.Description);
                Microsoft.MediaCenter.UI.Application.DeferredInvoke(new DeferredHandler(AddItemToSearchList), item);
            }
        }
        public void CreateNewSearchList(object obj)
        {
            string listName = obj.ToString();
            VirtualList tempVirtualList = new VirtualList();
            tempVirtualList.EnableSlowDataRequests = true;
            tempVirtualList.RequestSlowDataHandler = new RequestSlowDataHandler(CompleteMediaItem);
            tempVirtualList.StoreQueryResults = true;
            SearchResultsList.Add(listName, tempVirtualList);
        }

        public void AddItemToSearchList(object obj)
        {
            RssItem item = (RssItem)obj;
            Debug.WriteLine("AddItemToSearchList : " + item.Description);
            TVRssMediaItem mi = new TVRssMediaItem();
            mi.URL = item.Link;
            //mi.Name = TVRssPlugin.FixName(item.Title);
            Regex regexp = new Regex("Show Name: (?'ShowName'.*); Episode Title: (?'ShowTitle'.*); (?:(?:Season: (?'Season'[0-9]*); Episode:\\s*(?'Episode'[0-9]*))|(Episode Date:\\s*(?'EpisodeDate'.*)))", RegexOptions.IgnoreCase);
            Match match = regexp.Match(item.Description);
            mi.ShowName = match.Groups["ShowName"].ToString();
            mi.ShowTitle = match.Groups["ShowTitle"].ToString();
            int tempInt;
            Int32.TryParse(match.Groups["Season"].ToString(), out tempInt);
            mi.Season = tempInt;
            Int32.TryParse(match.Groups["Episode"].ToString(), out tempInt);
            mi.Episode = tempInt;
            mi.Description = item.Description;
            mi.Type = MediaItemType.TV;
            mi.Name = mi.ShowName + ((mi.Season != 0)?" (s" + mi.Season.ToString().PadLeft(2, '0') + " | e" + mi.Episode.ToString().PadLeft(2, '0') + ")":"");
            mi.Plugin = this;
            string filterName = (mi.Season == 0)?"Special":"TV Show";
            lock (Filters)
            {
                if (!Filters.Contains(filterName))
                    Filters.Add(filterName);
            }
            lock (SearchResultsList)
            {
                if (!SearchResultsList.ContainsKey(filterName))
                {
                    //CreateNewSearchList(showName);
                    SearchResultsList.Add(filterName, new VirtualList());
                }
            }
            SearchResultsList[filterName].Add(mi);
            SearchResultsCount++;
            //SearchResults.Add(mi);
        }

        public void CompleteMediaItem(VirtualList list, int index)
        {
            try
            {
                TVRssMediaItem mi = (TVRssMediaItem)list[index];
                if (mi.ShowName != "" && mi.Season != 0 && mi.Episode != 0)
                {
                    Episode episode = MediaDAL.GetEpisode(mi.ShowName, mi.Season, mi.Episode);
                    if (episode != null)
                    {
                        mi.Description = episode.Overview;
                        mi.ShowTitle = episode.Name;
                    }
                }
            }
            catch { }
        }

        public override IList GetSearchResults(string filter)
        {
            if (!SearchResultsList.ContainsKey(filter))
                return (IList) base.GetSearchResults(filter);
            else
                return (IList) SearchResultsList[filter];
        }

        //public override int SearchResultsCount
        //{
        //    get
        //    {
        //        return SearchResults.Count;
        //    }
        //    set
        //    {
        //        if (_SearchResultsCount != value)
        //        {
        //            _SearchResultsCount = value;
        //            FirePropertyChanged("SearchResultsCount");
        //            FirePropertyChanged("SearchLabel");
        //        }
        //    }
        //}

        public override string SearchLabel
        {
            get
            {
                return this.Name + " (" + SearchResultsCount + ")";
            }
            set
            {
                base.SearchLabel = value;
            }
        }

        public override void OnDetailsActionInvoked(DetailsCommand command)
        {
            base.OnDetailsActionInvoked(command);
            TVRssMediaItem item = (TVRssMediaItem)command.Owner;
            switch (command.Type)
            {
                case "Download":
                    bool value = false;
                    value = Application.Current.TorrentList.CurrentTorrentSession.AddTorrentFromURL(item.URL);
                    if (value)
                    {
                        Application.Current.MessageBox(Name + " downloading.", "Torrent Added", 4, true);
                        Application.Current.TorrentList.UpdateLists();
                    }
                    else
                        Application.Current.MessageBox("There was an error downloading " + Name, "Torrent Error", 4, true);
                    break;
            }
        }

        public override bool HasSearchInterface
        {
            get{ return true; }
        }

        #region Static Methods
        public static string FixName(string sInput)
        {
            string sOrigInput = sInput;
            string sExt = "", sSeason = "00", sEpisode = "00", sOutput = "";
            int iEndOfName = 0;
            sExt = sInput.Substring(sInput.LastIndexOf(".") + 1).ToLower();
            if (sExt.Length > 6)
            {
                sExt = "";
            }
            Regex regexp = new Regex(@"(?'ShowName'[^\-\[]+)(?:[\s]+-[\s]+(?'ShowTitle'[^\[]*))?(?:[\s]+(?'Season'[\d]{1,2})x(?'Episode'[\d]{1,2}))\s+\[(?'Properties'[^\]]+)\]",RegexOptions.IgnoreCase);
            sInput = sInput.ToUpper();
            sInput = sInput.Replace(" ", ".");
            sInput = sInput.Replace("-", ".");
            sInput = sInput.Replace("_", ".");

            string[] sTokens = sInput.Split('.');
            foreach (string sToken in sTokens)
            {
                iEndOfName = sInput.IndexOf(sToken) - 1;
                string sTokenFormat = sToken.Replace("0", "#").Replace("1", "#").Replace("2", "#").Replace("3", "#").Replace("4", "#").Replace("5", "#").Replace("6", "#").Replace("7", "#").Replace("8", "#").Replace("9", "#");
                if (sTokenFormat.Length <= 6 && sTokenFormat.StartsWith("S#") && sTokenFormat.Contains("E#"))
                {
                    sSeason = sToken.Substring(1, sToken.IndexOf("E") - 1);
                    sEpisode = sToken.Substring(sToken.IndexOf("E") + 1);
                    break;
                }
                if (sTokenFormat.Length <= 5 && sTokenFormat.Contains("#X#"))
                {
                    sSeason = sToken.Substring(0, sToken.IndexOf("X"));
                    sEpisode = sToken.Substring(sToken.IndexOf("X") + 1);
                    break;
                }
                if (sTokenFormat.Length >= 3 && sTokenFormat.Length <= 4 && sTokenFormat.Replace("#", "").Length == 0)
                {
                    if (sToken.Length == 3)
                    {
                        sSeason = sToken.Substring(0, 1);
                        sEpisode = sToken.Substring(1, 2);
                    }
                    if (sToken.Length == 4)
                    {
                        sSeason = sToken.Substring(0, 2);
                        sEpisode = sToken.Substring(2, 2);
                    }
                    break;
                }
            }

            try
            {
                if (sInput.StartsWith("THE."))
                    sOutput = TorrentItem.ProperCase(sInput.Substring(0, iEndOfName).Replace(".", " ")).Substring(4) + ", The (s" + sSeason.PadLeft(2, '0') + " | e" + sEpisode.PadLeft(2, '0') + ")" + ((sExt != "") ? "." + sExt : "");
                else
                    sOutput = TorrentItem.ProperCase(sInput.Substring(0, iEndOfName).Replace(".", " ")) + " (s" + sSeason.PadLeft(2, '0') + " | e" + sEpisode.PadLeft(2, '0') + ")" + ((sExt != "") ? "." + sExt : "");
                return sOutput;
            }
            catch
            {
                return sOrigInput;
            }
        }
        public static string ProperCase(string stringInput)
        {
            System.Text.StringBuilder sb = new System.Text.StringBuilder();
            bool fEmptyBefore = true;
            foreach (char ch in stringInput)
            {
                char chThis = ch;
                if (Char.IsWhiteSpace(chThis))
                    fEmptyBefore = true;
                else
                {
                    if (Char.IsLetter(chThis) && fEmptyBefore)
                        chThis = Char.ToUpper(chThis);
                    else
                        chThis = Char.ToLower(chThis);
                    fEmptyBefore = false;
                }
                sb.Append(chThis);
            }
            return sb.ToString();
        }
        #endregion

    }

    public class TVRssMediaItem : MediaItem, IMediaItem
    {

        private String _ShowName;

        public String ShowName
        {
            get { return _ShowName; }
            set
            {
                if (value != _ShowName)
                {
                    _ShowName = value;
                    FirePropertyChanged("ShowName");
                }
            }
        }

        private String _ShowTitle;

        public String ShowTitle
        {
            get { return _ShowTitle; }
            set
            {
                if (value != _ShowTitle)
                {
                    _ShowTitle = value;
                    FirePropertyChanged("ShowTitle");
                }
            }
        }

        private int _Season;

        public int Season
        {
            get { return _Season; }
            set
            {
                if (value != _Season)
                {
                    _Season = value;
                    FirePropertyChanged("Season");
                }
            }
        }

        private int _Episode;

        public int Episode
        {
            get { return _Episode; }
            set
            {
                if (value != _Episode)
                {
                    _Episode = value;
                    FirePropertyChanged("Episode");
                }
            }
        }

        public override string ListDisplayProperties
        {
            get
            {
                return @"{\rtf1\ansi\ansicpg1252\deff0\deflang1033{\fonttbl{\f0\fswiss\fcharset0 Segeo;}}{\colortbl ;\red255\green255\blue255;}{\*\generator Msftedit 5.41.21.2508;}\viewkind4\uc1\pard\cf1\b\f0\fs28 Name\b0  : " + Name + @"\par\b Show Name\b0 : " + ShowName + @"\par\b Show Title\b0 : " + ShowTitle + @"\par \b Season\b0 : " + Season + @"\tab\tab \b Episode\b0 : " + Episode + @" \par}";
            }
        }
        
        public override ArrayListDataSet Commands
        {
            get
            {
                if (_Commands == null)
                {
                    _Commands = new ArrayListDataSet(this);

                    _Commands.Add(Plugin.CreateCommand(this, "Download", "Download", this.Name));
                }
                return _Commands;
            }
        }

    }
}
